package com.example.searchenginebackend.components;

import com.example.searchenginebackend.model.Document;
import com.example.searchenginebackend.model.RelativePair;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.ansj.domain.Result;
import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.example.searchenginebackend.constant.IndexConstant.*;
import static com.example.searchenginebackend.constant.IndexConstant.INVERTED_INDEX_PATH;

@Component
public class IndexComponent {
    @Resource
    private ObjectMapper objectMapper;
    List<Document> forwardIndex = new ArrayList<>(); // 正排索引
    Map<String, List<RelativePair>> invertedIndex = new HashMap<>(); // 倒排索引

    /**
     * 获取正排索引
     * @param docId 文档id
     * @return 文档
     */
    public Document getDocById(int docId) {
        return forwardIndex.get(docId);
    }

    /**
     * 查询倒排索引
     * @param keyword 关键词
     * @return 与查询词相关文档构成的列表
     */
    public List<RelativePair> getRelativePairList(String keyword) {
        return invertedIndex.get(keyword);
    }

    /**
     * 保存索引
     */
    public void save() {
        try {
            // 保存正排索引
            File forwardIndexFile = new File(FORWARD_INDEX_PATH);
            objectMapper.writeValue(forwardIndexFile, this.forwardIndex);
            // 保存倒排索引
            File invertedIndexFile = new File(INVERTED_INDEX_PATH);
            objectMapper.writeValue(invertedIndexFile, this.invertedIndex);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 加载索引
     */
    public void load() {
        // 1. 加载索引
        try {
            // 1.1 加载正排索引
            File forwardIndexFile = new File(FORWARD_INDEX_PATH);
            this.forwardIndex = objectMapper.readValue(forwardIndexFile, new TypeReference<List<Document>>() {});
            // 1.2 加载倒排索引
            File invertedIndexFile = new File(INVERTED_INDEX_PATH);
            this.invertedIndex = objectMapper.readValue(invertedIndexFile, new TypeReference<Map<String, List<RelativePair>>>() {});
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void addIndex(String title, String url, String content) {
        // 1. 构建正排索引
        Document document = addForwardIndex(title, url, content);
        // 2. 构建倒排索引
        addInvertedIndex(document);
    }

    /**
     * 构建倒排索引
     * @param document 文档
     */
    private void addInvertedIndex(Document document) {
        // 1. 获取相关数据
        String title = document.getTitle();
        String content = document.getContent();
        // 2. 解析title与content
        HashMap<String, int[]> weightMap = new HashMap<>();
        List<Term> titleTermList = ToAnalysis.parse(title).getTerms();
        for (Term titleTerm : titleTermList) {
            String key = titleTerm.getName();
            int[] weight = weightMap.get(key);
            if (weight == null) {
                weight = new int[] {KEY_IN_TITLE_WEIGHT, 0};
                weightMap.put(key, weight);
            } else {
                weight[0] += KEY_IN_TITLE_WEIGHT;
            }
        }
        List<Term> contentTermList = ToAnalysis.parse(content).getTerms();
        for (Term contentTerm : contentTermList) {
            String key = contentTerm.getName();
            int[] weight = weightMap.get(key);
            if (weight == null) {
                weight = new int[] {0, KEY_IN_CONTENT_WEIGHT};
                weightMap.put(key, weight);
            } else {
                weight[1] += KEY_IN_CONTENT_WEIGHT;
            }
        }
        // 3. 保存到倒排索引中
        for (Map.Entry<String, int[]> entry : weightMap.entrySet()) {
            String key = entry.getKey();
            int[] weightValue = entry.getValue();
            List<RelativePair> relativePairList = invertedIndex.get(key);
            if (relativePairList == null) {
                relativePairList = new ArrayList<>();
                invertedIndex.put(key, relativePairList);
            }
            relativePairList.add(new RelativePair(document.getDocId(), key, weightValue[0] + weightValue[1]));
        }
    }

    /**
     * 构建正排索引
     * @param title 文章标题
     * @param url 文章url
     * @param content 文章内容
     * @return 文档
     */
    private Document addForwardIndex(String title, String url, String content) {
        Document document = new Document();
        document.setDocId(forwardIndex.size());
        document.setTitle(title);
        document.setUrl(url);
        document.setContent(content);
        forwardIndex.add(document);
        return document;
    }

}
